package com.apes.fn.scm.retailOrder.service;

import com.alibaba.fastjson.JSONObject;
import com.apes.fn.scm.retailOrder.model.CarWasherReport;
import com.apes.fn.scm.retailOrder.model.RetailOrder;
import com.apes.fn.scm.retailOrder.model.RetailOrderItem;
import com.apes.fn.scm.retailOrder.repository.CarWasherReportRepository;
import com.apes.fn.scm.retailOrder.repository.RetailOrderRepository;
import com.apes.framework.api.DomainService;
import com.apes.framework.api.SpringManager;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.util.DateUtil;
import com.apes.framework.util.MapUtil;
import com.apes.hr.area.model.DeptAreaItem;
import com.apes.hr.area.repository.DeptAreaItemRepository;
import com.apes.hr.base.model.Employee;
import com.apes.hr.base.repository.EmployeeRepository;
import com.apes.scm.masterdata.frame.model.Store;
import com.apes.scm.masterdata.frame.repository.StoreRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @program: apes-server
 * @description 洗美报表统计
 * @author: czs
 * @create: 2021-11-24 10:56
 **/
@Service("carWasherReportService")
public class CarWasherReportService extends DomainService {

    @Autowired
    CarWasherReportRepository carWasherReportRepository;
    @Autowired
    private RetailOrderRepository retailOrderRepository;
    @Autowired
    private StoreRepository storeRepository;
    @Autowired
    private DeptAreaItemRepository deptAreaItemRepository;


    private Map<String,String> parameterBinding = new HashMap<String,String>(){
        {
            this.putAll(MapUtil.mapper(
                    "S010101","common",
                    "S010102","common",
                    "S010103","deep",
                    "S01020202","wax",
                    "S01020204","crystal",
                    "S01020103003","dry",
                    "S01020201002","engine",
                    "S01020103002","catalyst",
                    "S01020103","air",
                    "S0102","beauty",
                    "S01020201004","serve"));
        }
    };

    /**
     * 批量日结
     * @param request
     */
    private void batchDailyWasherBeauty(SimpleRequest request){
        JSONObject requestJO = request.getJO();
        Date startDate = requestJO.getDate("startDate");
        Date endDate = requestJO.getDate("endDate");
        if (startDate==null||endDate==null) throw new RuntimeException("请传入开始结束日期");
        while (startDate.getTime()<=endDate.getTime()){
            Calendar endDateCalendar = Calendar.getInstance();
            endDateCalendar.setTime(startDate);
            endDateCalendar.add(Calendar.DATE,1);
            Date end = endDateCalendar.getTime();
            dateDailyWasherBeauty(startDate,end);
            startDate =end;
        }
    }

    /**
     * 日结洗美报表
     * @param request
     */
    private void dailyWasherBeauty(SimpleRequest request){
        Date date = new Date();
        Date startTemp = DateUtil.parse(DateUtil.format(date, DateUtil.SHOW_DATE_FORMAT), DateUtil.SHOW_DATE_FORMAT);
        Date start = DateUtil.parse(DateUtil.timeStampToStr(startTemp.getTime()-86400000L), DateUtil.SHOW_DATE_FORMAT);
        Date end = DateUtil.parse(DateUtil.timeStampToStr(startTemp.getTime()), DateUtil.SHOW_DATE_FORMAT);
        dateDailyWasherBeauty(start,end);
    }


    /**
     * 单日日结
     * @param start
     * @param end
     */
    private void dateDailyWasherBeauty(Date start, Date end){


        Map<String, List<RetailOrder>> retailOrderCollect = retailOrderRepository.findAllByPostDate(start, end).stream().collect(Collectors.groupingBy(retailOrder -> retailOrder.getDept().getId()));

        for (String s : retailOrderCollect.keySet()) {

            CarWasherReport carWasherReport = new CarWasherReport();

            List<RetailOrder> retailOrders = retailOrderCollect.get(s);
            carWasherReport.setStatisticDate(start);
            RetailOrder retailOrder = retailOrders.stream().findAny().get();
            DeptAreaItem deptAreaItem = deptAreaItemRepository.findByDept(retailOrder.getDept());
            if (deptAreaItem!=null)carWasherReport.setDeptArea(deptAreaItem.getDeptArea());
            carWasherReport.setDept(retailOrder.getDept());
            Store store = storeRepository.findByDept(retailOrder.getDept());
            if (store!=null)carWasherReport.setStoreLevels(store.getStoreLevels());

            for (String classify : parameterBinding.keySet()) {
                String field = parameterBinding.get(classify);
                carWasherReport.setField(field,getCountAndAmount(classify, retailOrders));
            }
            getYearCard(retailOrders,carWasherReport);
            getSupervisor(retailOrders,carWasherReport);
            carWasherReport.sumAmountN();
            carWasherReportRepository.saveAndFlush(carWasherReport);
        }

    }

    private boolean checkNeedSave(CarWasherReport carWasherReport){
        return carWasherReport.getWasherBeautyAmount()==0&&(carWasherReport.getSupervisorId()==null||carWasherReport.getSupervisorAmount()==0);
    }

    private void getSupervisor(List<RetailOrder> retailOrders, CarWasherReport carWasherReport) {
        Employee supervisor = SpringManager.getBean(EmployeeRepository.class).findByWorkBranch(carWasherReport.getDept().getBranch()).stream().filter(employee -> employee.getPost().getId().equals("0000002")).findFirst().orElse(null);
        if (supervisor==null)return;
        double amount = retailOrders.stream()
                .filter(retailOrder -> retailOrder.getClerk().getParty().getId() == supervisor.getParty().getId())
                .mapToDouble(retailOrder -> retailOrder.getSaleItems().stream()
                        .mapToDouble(RetailOrderItem::getPriceTotal)
                        .reduce(Double::sum)
                        .orElse(0))
                .reduce(Double::sum)
                .orElse(0);
        carWasherReport.setSupervisorId(supervisor.getParty().getPatyRoleByType("Employee"));
        carWasherReport.setSupervisorAmount(amount);
        carWasherReport.setSupervisorName(supervisor.getName());

    }

    private Map<String,Double> getCountAndAmount(String classify,List<RetailOrder> retailOrders){

        List<RetailOrder> baseCollect = retailOrders.stream()
                .filter(retailOrder -> {
                    List<RetailOrderItem> collect = retailOrder.getSaleItems().stream()
                            .filter(retailOrderItem -> retailOrderItem.getProduct().getClassify().getId().startsWith(classify))
                            .collect(Collectors.toList());
                    return collect.size() > 0;
        }).collect(Collectors.toList());

        Integer count = baseCollect.stream().collect(Collectors.groupingBy(retailOrder -> retailOrder.getCustomerExpand().getCarLicense())).size();


        double amount = baseCollect.stream()
                .mapToDouble(retailOrder -> retailOrder.getSaleItems().stream()
                        .filter(retailOrderItem -> retailOrderItem.getProduct().getClassify().getId().startsWith(classify))
                        .mapToDouble(retailOrderItem ->{
                            double discount = retailOrderItem.getRetailDiscounts().stream().mapToDouble(retailDiscount -> {
                                if (retailDiscount.checkIsYearCard()) return retailDiscount.getDiscountAmount()+retailDiscount.getCouponProfitAmount();
                                return retailDiscount.getDiscountAmount();
                            }).reduce(Double::sum).orElse(0);
                            return retailOrderItem.getPriceTotal()-discount;
                        })
                        .reduce(Double::sum).orElse(0))
                .sum();

        return mapper("count",count.doubleValue(),"amount",amount);
    }

    private void getYearCard(List<RetailOrder> retailOrders,CarWasherReport carWasherReport){

        List<RetailOrder> baseCollect = retailOrders.stream().filter(retailOrder -> retailOrder.getYearCardType()!=null&&retailOrder.getYearCardType().equals("01")).collect(Collectors.toList());

        int count = baseCollect.size();
        double amount = baseCollect.stream()
                .mapToDouble(retailOrder -> retailOrder.getSaleItems().stream()
                        .filter(retailOrderItem -> retailOrderItem.getProduct().getId().equals("0002118734")||retailOrderItem.getProduct().getId().equals("0002118743"))
                        .mapToDouble(RetailOrderItem::getPriceTotal)
                        .reduce(Double::sum).orElse(0))
                .sum();

        carWasherReport.setBeautyCardAmount(amount);
        carWasherReport.setBeautyCardCount(count);
    }


}
